﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Cesave.Domain.Core;
using Cesave.Domain.PermisosModule.Entities;
using Cesave.Domain.PermisosModule.Resources;

namespace Cesave.Domain.PermisosModule.Contracts.Distritos
{
	public class DistritoService
		: IDistritoService
	{
		#region Private properties

		private readonly IDistritoRepository _distritoRepository;

		#endregion

		#region Constructor

		/// <summary>
		/// 
		/// </summary>
		/// <param name="distritoRepository"></param>
		public DistritoService(IDistritoRepository distritoRepository)
		{
			if (distritoRepository == null)
				throw new ArgumentNullException("distritoRepository", Messages.exception_DependenciesAreNotInitialized);
			_distritoRepository = distritoRepository;
		}

		#endregion

		#region IDistritoService Members

		/// <summary>
		/// 
		/// </summary>
		/// <param name="estadoGuid"></param>
		/// <returns></returns>
		public List<Distrito> FindDistritosByEstado(Guid estadoGuid)
		{
			if (estadoGuid == Guid.Empty)
				throw new InvalidOperationException(Messages.exception_InvalidArgument);
			DistritosByEstadoSpecification distritosByEstadoSpecification = new DistritosByEstadoSpecification(estadoGuid);
			return _distritoRepository.FindDistritosByEstadoSpecification(distritosByEstadoSpecification).ToList();
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="estadoGuid"></param>
		/// <param name="status"></param>
		/// <returns></returns>
		public List<Distrito> FindDistritosByEstadoAndStatus(Guid estadoGuid, bool status = true)
		{
			if (estadoGuid == Guid.Empty)
				throw new InvalidOperationException(Messages.exception_InvalidArgument);
			DistritosByEstadoSpecification distritosByEstadoSpecification = new DistritosByEstadoSpecification(estadoGuid);
			DistritosByStatusSpecification distritosByStatusSpecification = new DistritosByStatusSpecification(status);
			return _distritoRepository.FindDistritosByEstadoAndStatusSpecification(distritosByEstadoSpecification, distritosByStatusSpecification).ToList();
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="distritoGuid"></param>
		/// <returns></returns>
		public Distrito FindDistritoByGuid(Guid distritoGuid)
		{
			if (distritoGuid == Guid.Empty)
				throw new InvalidOperationException(Messages.exception_InvalidArgument);
			DistritoByGuidSpecification distritoByIdSpecification = new DistritoByGuidSpecification(distritoGuid);
			return _distritoRepository.FindDistritoByGuidSpecification(distritoByIdSpecification);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="distrito"></param>
		public void AddDistrito(Distrito distrito)
		{
			if (distrito == null)
				throw new ArgumentNullException("distrito", Messages.exception_InvalidArgument);
			IUnitOfWork unitOfWork = _distritoRepository.StoreContext;
			_distritoRepository.Add(distrito);
			try
			{
				unitOfWork.Commit();
			}
			catch (OptimisticConcurrencyException)
			{
				unitOfWork.RollbackChanges();
				unitOfWork.CommitAndRefreshChanges();
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="distrito"></param>
		public void ChangeDistrito(Distrito distrito)
		{
			if (distrito == null)
				throw new ArgumentNullException("distrito", Messages.exception_InvalidArgument);
			IUnitOfWork unitOfWork = _distritoRepository.StoreContext;
			_distritoRepository.Modify(distrito);
			try
			{
				unitOfWork.Commit();
			}
			catch (OptimisticConcurrencyException)
			{
				unitOfWork.RollbackChanges();
				unitOfWork.CommitAndRefreshChanges();
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="distrito"></param>
		public void DeleteDistrito(Distrito distrito)
		{
			if (distrito == null)
				throw new ArgumentNullException("distrito", Messages.exception_InvalidArgument);
			IUnitOfWork unitOfWork = _distritoRepository.StoreContext;
			_distritoRepository.Remove(distrito);
			try
			{
				unitOfWork.Commit();
			}
			catch (OptimisticConcurrencyException)
			{
				unitOfWork.RollbackChanges();
				unitOfWork.CommitAndRefreshChanges();
			}
		}

		#endregion

		#region IDisposable Members

		public void Dispose()
		{
			if (_distritoRepository != null &&
				_distritoRepository.StoreContext != null)
				_distritoRepository.StoreContext.Dispose();
		}

		#endregion
	}
}
